import { GitCompareArrows } from 'lucide-react'; import Link from 'next/link'; import { notFound } from 'next/navigation'; import { Suspense } from 'react'; import { Bars } from '@/components/charts/bars'; import { LineChart } from '@/components/charts/line-chart'; import { WorldMap } from '@/components/charts/world-map'; import { CompanyHeader, DensityStrip } from '@/components/company/company-header'; import { CompanyMiniList } from '@/components/company/company-table'; import { MetricTiles } from '@/components/company/metric-tiles'; import { ConfidenceLegend, HistoryPanel, JobsPanel, LocationsPanel, PeoplePanel, PricingPanel, ProductsPanel, SensorsTable, SignalsPanel, TimelinePanel } from '@/components/company/panels'; import { CorporateStructurePanel, KeyFactsPanel } from '@/components/company/profile-panels'; import { EventList } from '@/components/events/event-row'; import { Chip } from '@/components/ui/badges'; import { KV, Row } from '@/components/ui/key-value'; import { Container, Empty, Note } from '@/components/ui/section'; import { TabPanel, Tabs } from '@/components/ui/tabs'; import { api, ApiError, safe } from '@/lib/api'; import { fmtDate, fmtPct, humanize } from '@/lib/format'; import { bool, str, type SP } from '@/lib/params'; import { sourceFor } from '@/lib/profile'; import { routes, SURFACE_LABELS } from '@/lib/site'; import type { CompanyDetail, MapBucket } from '@/lib/types'; export const revalidate = 120; const TABS = [ { id: 'overview', label: 'Overview' }, { id: 'timeline', label: 'Timeline' }, { id: 'signals', label: 'Signals' }, { id: 'jobs', label: 'Jobs' }, { id: 'products', label: 'Products' }, { id: 'pricing', label: 'Pricing' }, { id: 'locations', label: 'Locations' }, { id: 'leadership', label: 'Leadership' }, { id: 'sources', label: 'Sources' }, { id: 'history', label: 'History' }, ]; export default async function CompanyPage({ params, searchParams }: { params: Promise<{ slug: string }>; searchParams: Promise }) { const { slug } = await params; const sp = await searchParams; let c: CompanyDetail; try { c = await api.company(slug); } catch (e) { if (e instanceof ApiError && e.notFound) notFound(); throw e; } const requested = str(sp.tab) ?? 'overview'; const tab = TABS.some((t) => t.id === requested) ? requested : 'overview'; const tabs = TABS.map((t) => ({ ...t, count: t.id === 'jobs' ? c.counts.jobs_open : t.id === 'sources' ? c.counts.sensors : t.id === 'signals' ? c.signals?.length || undefined : undefined })); // Products tab fallback: Wikidata "product or material produced" statements, with the provenance of that field. const wdProducts = c.profile?.products ?? []; const wdSrc = sourceFor(c.profile, 'products'); const wdSource = wdSrc ? { url: wdSrc.url, retrieved_at: wdSrc.retrieved_at } : c.profile?.wikidata_url ? { url: c.profile.wikidata_url, retrieved_at: c.profile.enriched_at ?? '' } : null; return ( {tab === 'overview' && } {tab === 'timeline' && } {tab === 'signals' && } {tab === 'jobs' && } {tab === 'products' && } {tab === 'pricing' && } {tab === 'locations' && } {tab === 'leadership' && } {tab === 'sources' && } {tab === 'history' && }

Compare {c.display_name} with peers on activity, hiring, product velocity, AI adoption, locations and events.

Compare companies
); } async function Overview({ c }: { c: CompanyDetail }) { const [events, similar, metrics] = await Promise.all([safe(api.companyEvents(c.slug, { per_page: 10 })), safe(api.companySimilar(c.slug, 8)), safe(api.companyMetrics(c.slug, 90))]); const surfaces = Object.entries(c.sensors_by_surface ?? {}).sort((a, b) => b[1] - a[1]); const series = metrics?.series ?? {}; const lines = (['activity_score', 'product_velocity', 'ai_adoption'] as const).filter((k) => (series[k]?.length ?? 0) > 1).map((k) => ({ id: k, label: humanize(k), points: series[k]!.map((p) => ({ day: p.day, value: p.value })) })); return (

Latest structured events

{events ? : } {events && events.total > 10 && (

Full timeline ({events.total} events) →

)}

90-day metric series

{lines.length ? : }
{c.signals?.length > 0 && (

Active signals

)}
); } async function Locations({ slug }: { slug: string }) { const data = await safe(api.companyLocations(slug)); const buckets: MapBucket[] = (data?.items ?? []).filter((l) => l.status === 'listed' && l.lat !== null && l.lon !== null).map((l) => ({ lat: l.lat as number, lon: l.lon as number, country: l.country ?? '', city: l.city, companies: 1, events_30d: 1, jobs_open: 0, top: [] })); return b.country))]} /> : No geocoded locations to draw yet.} />; } async function Sources({ c }: { c: CompanyDetail }) { const data = await safe(api.companySensors(c.slug)); if (!data) return ; const items = [...data.items].sort((a, b) => (a.status === b.status ? b.event_count - a.event_count : a.status === 'active' ? -1 : 1)); return (
Every fact on this profile traces back to one of these sensors. A sensor is a deployed connector watching one public URL on a schedule (tier A = 5–15 min … E = 3–7 days). Open a sensor for its observations, snapshots and changes.
); }